﻿using Microsoft.Xna.Framework;
using System;

namespace block_explorer
{
    // a simple container to make naming and handling of
    // sector addresses easier.
    // essentially just a Vector3 of ints.
    public class SectorAddress
    {
        private int mX;
        private int mY;
        private int mZ;
        private int mHashCode;

        public int X { get { return mX; } }
        public int Y { get { return mY; } }
        public int Z { get { return mZ; } }

        public SectorAddress()
        {
            mX = 0;
            mY = 0;
            mZ = 0;

            GenHash();
        }

        public SectorAddress(int x, int y, int z)
        {
            mX = x;
            mY = y;
            mZ = z;

            GenHash();
        }

        public SectorAddress(Vector3 address)
        {
            mX = (int)Math.Floor(address.X);
            mY = (int)Math.Floor(address.Y);
            mZ = (int)Math.Floor(address.Z);

            GenHash();
        }

        public static SectorAddress operator +(SectorAddress lhs, SectorAddress rhs)
        {
            return new SectorAddress(lhs.X + rhs.X, lhs.Y + rhs.Y, lhs.Z + rhs.Z);
        }

        public static SectorAddress operator -(SectorAddress lhs, SectorAddress rhs)
        {
            return new SectorAddress(lhs.X - rhs.X, lhs.Y - rhs.Y, lhs.Z - rhs.Z);
        }

        public Vector3 ToWorldPosition()
        {
            return new Vector3(mX * MapSector.SIZE, mY * MapSector.SIZE, mZ * MapSector.SIZE);
        }

        public static SectorAddress FromWorldPosition(Vector3 worldPosition)
        {
            return new SectorAddress((int)Math.Floor(worldPosition.X / MapSector.SIZE),
                                     (int)Math.Floor(worldPosition.Y / MapSector.SIZE),
                                     (int)Math.Floor(worldPosition.Z / MapSector.SIZE));
        }

        public override string ToString()
        {
            return X + ", " + Y + ", " + Z;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            SectorAddress other = (SectorAddress)obj;
            if (other == null) return false;
            return X == other.X && Y == other.Y && Z == other.Z;
        }

        public static bool operator ==(SectorAddress address1, SectorAddress address2) 
        {
            return address1.Equals(address2);
        }

        public static bool operator !=(SectorAddress address1, SectorAddress address2)
        {
            return !address1.Equals(address2);
        }

        public override int GetHashCode()
        {
            return mHashCode;
        }

        private void GenHash()
        {
            int result = mX.GetHashCode();
            result = (result * 397) ^ mY.GetHashCode();
            result = (result * 397) ^ mZ.GetHashCode();
            mHashCode = result;
        }
    }
}
